package xworker.lang.task.flow;

import org.xmeta.Thing;
import xworker.lang.executor.Executor;
import xworker.lang.task.TaskManager;
import xworker.lang.util.UtilData;

import java.util.List;
import java.util.concurrent.Future;

public class TaskFlowTask implements Runnable{
    private static final String TAG = TaskFlowTask.class.getName();

    TaskFlowTask parentTask;
    TaskFlow taskFlow;
    Thing thing;
    /**　任务实例的标识　*/
    String name;
    boolean started = false;
    Object result = null;
    Exception exception = null;
    Future<?> taskFuture;

    public TaskFlowTask(Thing thing, TaskFlow taskFlow){
        this.thing = thing;
        this.taskFlow = taskFlow;
        this.parentTask = null;
        this.name = thing.getMetadata().getName();
    }

    public TaskFlowTask(Thing thing, TaskFlowTask parentTask){
        this.thing = thing;
        this.taskFlow = parentTask.getTaskFlow();
        this.parentTask = parentTask;
        this.name = thing.getMetadata().getName();
    }

    /**
     * 返回任务是否可以执行了。
     */
    public boolean isReady(){
        return UtilData.isTrue(thing.doAction("isReady", taskFlow.getActionContext(), "task", this));
    }

    public boolean isStarted(){
        return started;
    }

    public String getName() {
        return name;
    }

    public TaskFlow getTaskFlow() {
        return taskFlow;
    }

    public Thing getThing() {
        return thing;
    }

    public void execute(){
        started = true;
        taskFuture = TaskManager.getExecutorService().submit(this);
    }

    public void cancel(){
        if(taskFuture != null && !taskFuture.isDone()){
            taskFuture.cancel(true);
        }
    }

    public boolean isFinished(){
        return taskFuture != null && taskFuture.isDone();
    }

    public List<TaskFlowTask> getNextTasks(){
        return thing.doAction("getNextTasks", taskFlow.getActionContext(), "task", this);
    }

    @Override
    public void run() {
        try{
            result = thing.doAction("doTask", taskFlow.getActionContext(), "task", this);
        }catch(Exception e){
            this.exception = e;
            Executor.warn(TAG, "Execute task exception, task=" + thing.getMetadata().getPath(), e);
        }finally {
            taskFlow.fireTaskFinished(this);
        }
    }

    public boolean isSuccess(){
        return isFinished() && exception == null;
    }

    public TaskFlowTask getParentTask() {
        return parentTask;
    }

    public Object getResult() {
        return result;
    }

    public Exception getException() {
        return exception;
    }
}
